home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / src890906.arc / NR4SUBR.C < prev    next >
C/C++ Source or Header  |  1989-08-12  |  8KB  |  390 lines

  1. /*
  2.  * nr4subr.c:  subroutines for net/rom transport layer.
  3.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  4.  * non-commercial distribution only.
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "timer.h"
  11. #include "ax25.h"
  12. #include "netrom.h"
  13. #include "nr4.h"
  14. #include "lapb.h"
  15. #include <ctype.h>
  16.  
  17. /* Convert a net/rom transport header to host format structure.
  18.  * Return -1 if error, 0 if OK.
  19.  */
  20.  
  21. int
  22. ntohnr4(hdr,bpp)
  23. register struct nr4hdr *hdr ;
  24. struct mbuf **bpp ;
  25. {
  26.     char axbuf[AXALEN] ;
  27.     unsigned char tbuf[NR4MINHDR] ;
  28.  
  29.     if (pullup(bpp, tbuf, NR4MINHDR) < NR4MINHDR)
  30.         return -1 ;
  31.  
  32.     hdr->opcode = tbuf[4] ;
  33.  
  34.     switch (tbuf[4] & NR4OPCODE) {
  35.  
  36.         case NR4OPPID:            /* protocol ID extension */
  37.             hdr->u.pid.family = tbuf[0] ;
  38.             hdr->u.pid.proto = tbuf[1] ;
  39.             break ;
  40.  
  41.         case NR4OPCONRQ:        /* connect request */
  42.             hdr->u.conreq.myindex = tbuf[0] ;
  43.             hdr->u.conreq.myid = tbuf[1] ;
  44.             if (pullup(bpp,&(hdr->u.conreq.window), 1) < 1)
  45.                 return -1 ;
  46.             if (pullup(bpp,axbuf,AXALEN) < AXALEN)
  47.                 return -1 ;
  48.             (void)getaxaddr(&hdr->u.conreq.user,axbuf) ;
  49.             if (pullup(bpp,axbuf,AXALEN) < AXALEN)
  50.                 return -1 ;
  51.             (void)getaxaddr(&hdr->u.conreq.node,axbuf) ;
  52.             break ;
  53.  
  54.         case NR4OPCONAK:        /* connect acknowledge */
  55.             hdr->yourindex = tbuf[0] ;
  56.             hdr->yourid = tbuf[1] ;
  57.             hdr->u.conack.myindex = tbuf[2] ;
  58.             hdr->u.conack.myid = tbuf[3] ;
  59.             if (pullup(bpp,&(hdr->u.conack.window), 1) < 1)
  60.                 return -1 ;
  61.             break ;
  62.  
  63.         case NR4OPDISRQ:        /* disconnect request */
  64.             hdr->yourindex = tbuf[0] ;
  65.             hdr->yourid = tbuf[1] ;
  66.             break ;
  67.  
  68.         case NR4OPDISAK:        /* disconnect acknowledge */
  69.             hdr->yourindex = tbuf[0] ;
  70.             hdr->yourid = tbuf[1] ;
  71.             break ;
  72.  
  73.         case NR4OPINFO:            /* information frame */
  74.             hdr->yourindex = tbuf[0] ;
  75.             hdr->yourid = tbuf[1] ;
  76.             hdr->u.info.txseq = tbuf[2] ;
  77.             hdr->u.info.rxseq = tbuf[3] ;
  78.             break ;
  79.  
  80.         case NR4OPACK:            /* information acknowledge */
  81.             hdr->yourindex = tbuf[0] ;
  82.             hdr->yourid = tbuf[1] ;
  83.             hdr->u.ack.rxseq = tbuf[3] ;
  84.             break ;
  85.  
  86.         default:                /* what kind of frame is this? */
  87.             return -1 ;
  88.     }
  89.  
  90.     return 0 ;
  91. }
  92.  
  93.  
  94. struct mbuf *
  95. htonnr4(hdr)
  96. register struct nr4hdr *hdr ;
  97. {
  98.     static unsigned char hlen[NR4NUMOPS] = {5,20,6,5,5,5,5} ;
  99.     struct mbuf *rbuf ;
  100.     register char *cp ;
  101.     unsigned char opcode ;
  102.  
  103.     opcode = hdr->opcode & NR4OPCODE ;
  104.  
  105.     if (opcode >= NR4NUMOPS)
  106.         return NULLBUF ;
  107.  
  108.     if (hdr == (struct nr4hdr *)NULL)
  109.         return NULLBUF ;
  110.  
  111.     if ((rbuf = alloc_mbuf(hlen[opcode])) == NULLBUF)
  112.         return NULLBUF ;
  113.  
  114.     rbuf->cnt = hlen[opcode] ;
  115.     cp = rbuf->data ;
  116.  
  117.     cp[4] = hdr->opcode ;
  118.     
  119.     switch (opcode) {
  120.     
  121.         case NR4OPPID:
  122.             *cp++ = hdr->u.pid.family ;
  123.             *cp = hdr->u.pid.proto ;
  124.             break ;
  125.  
  126.         case NR4OPCONRQ:
  127.             *cp++ = hdr->u.conreq.myindex ;
  128.             *cp++ = hdr->u.conreq.myid ;
  129.             cp += 3 ;                        /* skip to sixth byte */
  130.             *cp++ = hdr->u.conreq.window ;
  131.             cp = putaxaddr(cp, &hdr->u.conreq.user) ;
  132.             (void) putaxaddr(cp, &hdr->u.conreq.node) ;
  133.             break ;
  134.  
  135.         case NR4OPCONAK:
  136.             *cp++ = hdr->yourindex ;
  137.             *cp++ = hdr->yourid ;
  138.             *cp++ = hdr->u.conack.myindex ;
  139.             *cp++ = hdr->u.conack.myid ;
  140.             cp++ ;                            /* already loaded pid */
  141.             *cp = hdr->u.conack.window ;
  142.             break ;
  143.  
  144.         case NR4OPDISRQ:
  145.             *cp++ = hdr->yourindex ;
  146.             *cp = hdr->yourid ;
  147.             break ;
  148.  
  149.         case NR4OPDISAK:
  150.             *cp++ = hdr->yourindex ;
  151.             *cp = hdr->yourid ;
  152.             break ;
  153.  
  154.         case NR4OPINFO:
  155.             *cp++ = hdr->yourindex ;
  156.             *cp++ = hdr->yourid ;
  157.             *cp++ = hdr->u.info.txseq ;
  158.             *cp = hdr->u.info.rxseq ;
  159.             break ;
  160.  
  161.         case NR4OPACK:
  162.             *cp++ = hdr->yourindex ;
  163.             *cp++ = hdr->yourid ;
  164.             *++cp = hdr->u.ack.rxseq ;    /* skip third byte (tricky yuck) */
  165.             break ;
  166.  
  167.     }
  168.  
  169.     return rbuf ;
  170. }
  171.  
  172.  
  173. /* Get a free circuit table entry, and allocate a circuit descriptor.
  174.  * Initialize control block circuit number and ID fields.
  175.  * Return a pointer to the circuit control block if successful,
  176.  * NULLNR4CB if not.
  177.  */
  178.  
  179. struct nr4cb *
  180. new_n4circ()
  181. {
  182.     int i ;
  183.     struct nr4cb *cb ;
  184.  
  185.     for (i = 0 ; i <  NR4MAXCIRC ; i++)        /* find a free circuit */
  186.         if (Nr4circuits[i].ccb == NULLNR4CB)
  187.             break ;
  188.  
  189.     if (i == NR4MAXCIRC)    /* no more circuits */
  190.         return NULLNR4CB ;
  191.  
  192.     if ((cb = Nr4circuits[i].ccb =
  193.          (struct nr4cb *)calloc(1,sizeof(struct nr4cb))) == NULLNR4CB)
  194.         return NULLNR4CB ;
  195.     else {
  196.         cb->mynum = i ;
  197.         cb->myid = Nr4circuits[i].cid ;
  198.         return cb ;
  199.     }
  200. }
  201.  
  202.  
  203. /* Set the window size for a circuit and allocate the buffers for
  204.  * the transmit and receive windows.  Set the control block window
  205.  * parameter.  Return 0 if successful, -1 if not.
  206.  */
  207.  
  208. int
  209. init_nr4window(cb, window)
  210. struct nr4cb *cb ;
  211. unsigned window ;
  212. {
  213.     
  214.     if (window == 0 || window > NR4MAXWIN) /* reject silly window sizes */
  215.         return -1 ;
  216.         
  217.     if ((cb->txbufs =
  218.          (struct nr4txbuf *)calloc(window,sizeof(struct nr4txbuf)))
  219.          == (struct nr4txbuf *)0)
  220.         return -1 ;
  221.  
  222.     if ((cb->rxbufs =
  223.          (struct nr4rxbuf *)calloc(window,sizeof(struct nr4rxbuf)))
  224.          == (struct nr4rxbuf *)0) {
  225.         free(cb->txbufs) ;
  226.         cb->txbufs = (struct nr4txbuf *)0 ;
  227.         return -1 ;
  228.     }
  229.  
  230.     cb->window = window ;
  231.     
  232.     return 0 ;
  233. }
  234.  
  235.  
  236. /* Free a circuit.  Deallocate the control block and buffers, and
  237.  * increment the circuit ID.  No return value.
  238.  */
  239.  
  240. void
  241. free_n4circ(cb)
  242. struct nr4cb *cb ;
  243. {
  244.     unsigned circ ;
  245.  
  246.     if (cb == NULLNR4CB)
  247.         return ;
  248.  
  249.     circ = cb->mynum ;
  250.     
  251.     if (cb->txbufs != (struct nr4txbuf *)0)
  252.         free(cb->txbufs) ;
  253.  
  254.     if (cb->rxbufs != (struct nr4rxbuf *)0)
  255.         free(cb->rxbufs) ;
  256.  
  257.     /* Better be safe than sorry: */
  258.  
  259.     free_q(&cb->txq) ;
  260.     free_q(&cb->rxq) ;
  261.     
  262.     free(cb) ;
  263.  
  264.     if (circ > NR4MAXCIRC)        /* Shouldn't happen. */
  265.         return ;
  266.         
  267.     Nr4circuits[circ].ccb = NULLNR4CB ;
  268.  
  269.     Nr4circuits[circ].cid++ ;
  270. }
  271.  
  272. /* See if any open circuit matches the given parameters.  This is used
  273.  * to prevent opening multiple circuits on a duplicate connect request.
  274.  * Returns the control block address if a match is found, or NULLNR4CB
  275.  * otherwise.
  276.  */
  277.  
  278. struct nr4cb *
  279. match_n4circ(index, id, user, node)
  280. int index ;                    /* index of remote circuit */
  281. int id ;                    /* id of remote circuit */
  282. struct ax25_addr *user ;    /* address of remote user */
  283. struct ax25_addr *node ;    /* address of originating node */
  284. {
  285.     int i ;
  286.     struct nr4cb *cb ;
  287.  
  288.     for (i = 0 ; i < NR4MAXCIRC ; i++) {
  289.         if ((cb = Nr4circuits[i].ccb) == NULLNR4CB)
  290.             continue ;        /* not an open circuit */
  291.         if (cb->yournum == index && cb->yourid == id
  292.             && addreq((struct ax25_addr *)cb->remote.user_call,user)
  293.             && addreq((struct ax25_addr *)cb->remote.node_call,node))
  294.             return cb ;
  295.     }
  296.     /* if we get to here, we didn't find a match */
  297.  
  298.     return NULLNR4CB ;
  299. }
  300.  
  301. /* Validate the index and id of a local circuit, returning the control
  302.  * block if it is valid, or NULLNR4CB if it is not.
  303.  */
  304.  
  305. struct nr4cb *
  306. get_n4circ(index, id)
  307. int index ;                /* local circuit index */
  308. int id ;                /* local circuit id */
  309. {
  310.     struct nr4cb *cb ;
  311.  
  312.     if (index >= NR4MAXCIRC)
  313.         return NULLNR4CB ;
  314.  
  315.     if ((cb = Nr4circuits[index].ccb) == NULLNR4CB)
  316.         return NULLNR4CB ;
  317.  
  318.     if (cb->myid == id)
  319.         return cb ;
  320.     else
  321.         return NULLNR4CB ;
  322. }
  323.  
  324. /* Return 1 if b is "between" (modulo the size of an unsigned char)
  325.  * a and c, 0 otherwise.
  326.  */
  327.  
  328. int
  329. nr4between(a, b, c)
  330. unsigned a, b, c ;
  331. {
  332.     if ((a <= b && b < c) || (c < a && a <= b) || (b < c && c < a))
  333.         return 1 ;
  334.     else
  335.         return 0 ;
  336. }
  337.  
  338. /* Set up default timer values, etc., in newly connected control block.
  339.  */
  340.  
  341. void
  342. nr4defaults(cb)
  343. struct nr4cb *cb ;
  344. {
  345.     int i ;
  346.     struct timer *t ;
  347.  
  348.     if (cb == NULLNR4CB)
  349.         return ;
  350.  
  351.     /* Set up the ACK and CHOKE timers */
  352.     
  353.     cb->tack.start = Nr4acktime / MSPTICK ;
  354.     cb->tack.func = nr4ackit ;
  355.     cb->tack.arg = cb ;
  356.  
  357.     cb->tchoke.start = Nr4choketime / MSPTICK ;
  358.     cb->tchoke.func = nr4unchoke ;
  359.     cb->tchoke.arg = cb ;
  360.  
  361.     cb->rxpastwin = cb->window ;
  362.  
  363.     /* Don't actually set the timers, since this is done */
  364.     /* in nr4sbuf */
  365.     
  366.     for (i = 0 ; i < cb->window ; i++) {
  367.         t = &cb->txbufs[i].tretry ;
  368.         t->func = nr4txtimeout ;
  369.         t->arg = cb ;
  370.     }
  371. }
  372.  
  373. /* See if this control block address is valid */
  374.  
  375. int
  376. nr4valcb(cb)
  377. struct nr4cb *cb ;
  378. {
  379.     int i ;
  380.  
  381.     if (cb == NULLNR4CB)
  382.         return 0 ;
  383.         
  384.     for (i = 0 ; i < NR4MAXCIRC ; i++)
  385.         if (Nr4circuits[i].ccb == cb)
  386.             return 1 ;
  387.  
  388.     return 0 ;
  389. }
  390.